﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Repository;
using System.ComponentModel;
using System.Windows.Forms;
using System.Reflection;
using ProgNetComponents;
using DevExpress.XtraEditors.Controls;
using System.Data;
using ProgNetComponentsDx.Base.Components;
using ProgNetComponentsDx.Design.Painters;
using ProgNetComponents.Classes;
using ProgNetComponentsDx.Enums;
using System.ComponentModel.Design.Serialization;
using ProgNetComponentsDx.Browsers.Design;
using System.Collections;
using DevExpress.XtraBars;
using ProgNetComponentsDx.Controls.Editors;
using DevExpress.XtraEditors.ViewInfo;
using DevExpress.XtraEditors.Registrator;
using DevExpress.Accessibility;
using DevExpress.XtraEditors.Drawing;

namespace ProgNetComponentsDx.Browsers
{
    public class BrowserProvider : BaseExtenderProvider<BrowserSettings>
    {
        static BrowserProvider()
        {
            BrowserButtonId = new object();
            var einfo = EditorRegistrationInfo.Default.Editors["LookUpEdit"];
            if (einfo != null)
            {
                EditorRegistrationInfo.Default.Editors.Remove(einfo);
                einfo = new EditorClassInfo("LookUpEdit", typeof(LookUpEdit),
                    typeof(RepositoryItemLookUpEdit),
                    typeof(LookUpEditViewInfo),
                    (BaseEditPainter)new PNButtonEditPainter(), true, EditImageIndexes.LookUpEdit, typeof(PopupEditAccessible));
                EditorRegistrationInfo.Default.Editors.Add(einfo);
            }
        }

        public static object BrowserButtonId
        {
            get;
            set;
        }

        public BrowserProvider() { }
        public BrowserProvider(IContainer container) : base(container) { }
        
        protected override void ProcessObject(object target, BrowserSettings settings)
        {
            if (settings != null)
            {
                RepositoryItemTextEdit rep = null;
                if (target is RepositoryItemTextEdit)
                {
                    rep = (target as RepositoryItemTextEdit);
                    rep.Tag = rep;
                }
                if (target is TextEdit)
                    rep = (target as TextEdit).Properties;

                PrepareEdit(rep, settings);
            }
        }

        private void UpdateBrowserSettings(BrowserSettings s)
        {
            if (s.BrowserId != null && s.Browser == null)
                s.Browser = BrowserCache.GetBrowser(s.BrowserId);
        }

        private void PrepareEdit(RepositoryItemTextEdit edit, BrowserSettings s)
        {
            Browser b = BrowserCache.GetBrowser(s.BrowserId);

            s.Browser = b;
            if (b != null)
            {
                b.DisplayFilter = s.DisplayFilter;
            }
            edit.KeyDown -= new KeyEventHandler(rep_KeyDown);
            edit.Enter -= new EventHandler(edit_Enter);
            if (s != null && (s.AdditionalBrowserId != null || s.AddBrowserDialogButton))
            {
                edit.KeyDown += new KeyEventHandler(rep_KeyDown);
                edit.Enter += new EventHandler(edit_Enter);
            }

            if (edit is RepositoryItemGridLookUpEdit)
            {
                RepositoryItemGridLookUpEdit repGrid = edit as RepositoryItemGridLookUpEdit;
                if (b != null)
                {
                    BrowserCache.RefreshCacheForBrowser(s.BrowserId);
                    DataView dv = new DataView(BrowserCache.GetBrowserData(s.BrowserId, true));
                    dv.RowFilter = s.DisplayFilter;
                    repGrid.DataSource = dv;
                    repGrid.ValueMember = b.ValueMember;
                    repGrid.DisplayMember = b.DisplayMember;
                }
                else if(s.ShouldClearData)
                {
                    repGrid.DataSource = null;
                    repGrid.ValueMember = null;
                    repGrid.DisplayMember = null;
                    s.ShouldClearData = false;
                }
                PrepareLookup(repGrid, s, false);
            }
            else if (edit is RepositoryItemLookUpEditBase)
            {
                RepositoryItemLookUpEditBase rep = (edit as RepositoryItemLookUpEditBase);
                if (b != null)
                {
                    BrowserCache.RefreshCacheForBrowser(s.BrowserId);
                    DataView dv = new DataView(BrowserCache.GetBrowserData(s.BrowserId, true));
                    dv.RowFilter = s.DisplayFilter;
                    rep.DataSource = dv;
                    rep.ValueMember = b.ValueMember;
                    rep.DisplayMember = b.DisplayMember;
                }
                else if (s.ShouldClearData)
                {
                    rep.DataSource = null;
                    rep.ValueMember = null;
                    rep.DisplayMember = null;
                    s.ShouldClearData = false;
                }
                PrepareLookup(rep as RepositoryItemLookUpEdit, s, false);
            }
            else if (edit is RepositoryItemMultiSelectGridEdit)
            {
                RepositoryItemMultiSelectGridEdit rep = (edit as RepositoryItemMultiSelectGridEdit);
                if (b != null)
                {
                    BrowserCache.RefreshCacheForBrowser(s.BrowserId);
                    DataView dv = new DataView(BrowserCache.GetBrowserData(s.BrowserId, true));
                    dv.RowFilter = s.DisplayFilter;
                    rep.DataSource = dv;
                    rep.ValueMember = b.ValueMember;
                    rep.DisplayMember = b.DisplayMember;
                }
                else if (s.ShouldClearData)
                {
                    rep.DataSource = null;
                    rep.ValueMember = null;
                    rep.DisplayMember = null;
                    s.ShouldClearData = false;
                }
                PrepareLookup(rep as RepositoryItemMultiSelectGridEdit, s, false);
            }
            if (edit is RepositoryItemButtonEdit)
            {
                if (!this.IsDesignMode())
                {
                    RepositoryItemButtonEdit rep = edit as RepositoryItemButtonEdit;
                    if (s.Browser != null && s.MultiSelect)
                        rep.TextEditStyle = TextEditStyles.DisableTextEditor;

                    rep.ButtonClick -= new ButtonPressedEventHandler(rep_ButtonClick);
                    EditorButton btnAdd = null;
                    foreach (EditorButton btn in rep.Buttons)
                    {
                        if (btn.Tag == BrowserButtonId)
                        {
                            btnAdd = btn;
                        }
                    }
                    if (s != null && (s.AdditionalBrowserId != null || s.AddBrowserDialogButton))
                    {
                        rep.ButtonClick += new ButtonPressedEventHandler(rep_ButtonClick);
                    }
                    if (b != null && s.AddBrowserDialogButton)
                    {
                        if (btnAdd == null)
                            rep.Buttons.Add(new EditorButton(BrowserButtonId, s.BrowserDialogButtonType));
                        else
                            btnAdd.Kind = s.BrowserDialogButtonType;
                    }
                    else
                    {
                        if (btnAdd != null)
                            rep.Buttons.RemoveAt(rep.Buttons.IndexOf(btnAdd));
                    }
                }
            }
            SetAdditionalBrowser(edit, s);
        }
        
        void edit_Enter(object sender, EventArgs e)
        {
            TextEdit edit = sender as TextEdit;
            if (edit != null)
            {
                if (edit.EditValue.IsNotNull())
                {
                    Hashtable displayValues = edit.Properties.GetFieldValue("displayValues") as Hashtable;
                    if (displayValues != null)
                    {
                        if (displayValues.ContainsKey(edit.EditValue))
                        {
                            string text = string.Empty;
                            if (edit is LookUpEdit)
                                text = ((LookUpEdit)edit).Properties.GetDisplayValueByKeyValue(edit.EditValue).AsString();
                            else
                                text = edit.Properties.GetDisplayText(edit.EditValue);

                            CustomDisplayTextEventArgs ea = new CustomDisplayTextEventArgs(edit.EditValue, text);
                            edit.Properties.RunMethod("RaiseCustomDisplayText", ea);
                            displayValues[edit.EditValue] = ea.DisplayText;
                        }
                    }
                }
            }
        }

        private BrowserSettings GetSettingsForEdit(object obj)
        {
            BrowserSettings s = null;
            object o = GetRealKey(obj);

            if (AllObjects.ContainsKey(o))
                s = AllObjects[o];
            else if (obj is BaseEdit)
            {
                o = GetRealKey(((BaseEdit)obj).Properties);
                if (AllObjects.ContainsKey(o))
                    s = AllObjects[o];
            }
            return s;
        }

        private void ShowBrowserDialog(BaseEdit edit, BrowserSettings s)
        {
            if (edit != null && !edit.Properties.ReadOnly)
            {
                if (s != null && s.Browser != null && s.AddBrowserDialogButton)
                {
                    ObjectDialogResult dlg = s.Browser.ShowDialog(edit.EditValue, false, s.MultiSelect);
                    if (dlg.DialogResult == DialogResult.OK)
                        edit.EditValue = dlg.Value;
                }
            }
        }
        private void ShowAdditionalBrowserPopup(BaseEdit edit, BrowserSettings s)
        {
            if (edit != null && !edit.Properties.ReadOnly)
            {
                if (s != null && s.AdditionalBrowserId != null && s.AdditionalBrowserLookupEdit != null)
                {
                    Control c = s.AdditionalBrowserLookupEdit.Parent;
                    if (c != null)
                        c.Controls.Remove(s.AdditionalBrowserLookupEdit);

                    edit.Controls.Add(s.AdditionalBrowserLookupEdit);
                    s.AdditionalBrowserLookupEdit.Properties.LockEvents();
                    s.AdditionalBrowserLookupEdit.EditValue = edit.EditValue;
                    s.AdditionalBrowserLookupEdit.Properties.UnLockEvents();
                    s.AdditionalBrowserLookupEdit.ShowPopup();
                }
            }
        }

        private void rep_ButtonClick(object sender, ButtonPressedEventArgs e)
        {
            if (e.Button.Tag == BrowserButtonId)
            {
                var s = GetSettingsForEdit(sender);
                if (s != null)
                    ShowBrowserDialog(sender as BaseEdit, s);
            }
            else if (e.Button.Tag is BrowserSettings)
            {
                var s = GetSettingsForEdit(sender);
                if (s != null)
                    ShowAdditionalBrowserPopup(sender as BaseEdit, s);
            }
        }
        private void rep_KeyDown(object sender, KeyEventArgs e)
        {
            BaseEdit edit = sender as BaseEdit;
            BrowserSettings s = GetSettingsForEdit(sender);
            if (edit != null && s != null)
            {
                if (e.KeyCode == s.BrowserDialogPopupKey)
                {
                    ShowBrowserDialog(edit, s);
                }
                else if (e.KeyCode == s.AdditionalBrowserPopupKey)
                {
                    ShowAdditionalBrowserPopup(edit, s);
                }
            }
        }

        protected override object GetRealKey(object target)
        {
            if (target is RepositoryItem &&
                (target as RepositoryItem).Tag != null &&
                (target as RepositoryItem).Tag is RepositoryItem)
                return (target as RepositoryItem).Tag as RepositoryItem;

            return target;
        }

        #region additional browser
        private void SetAdditionalBrowser(RepositoryItemTextEdit edit, BrowserSettings s)
        {
            if (!this.IsDesignMode())
            {
                Browser ab = BrowserCache.GetBrowser(s.AdditionalBrowserId);
                s.AdditionalBrowser = ab;
                if (ab != null)
                {
                    ab.DisplayFilter = s.AdditionalBrowserDisplayFilter;
                }
                RepositoryItemButtonEdit buttonEdit = (edit as RepositoryItemButtonEdit);
                EditorButton button = null;

                edit.CustomDisplayText -= new CustomDisplayTextEventHandler(edit_CustomDisplayText);
                edit.FormatEditValue -= new ConvertEditValueEventHandler(edit_FormatEditValue);
                if (buttonEdit != null)
                {
                    foreach (EditorButton btn in buttonEdit.Buttons)
                    {
                        if (btn.Tag == s)
                        {
                            button = btn;
                            break;
                        }
                    }
                }
                if(ab!=null || s.MultiSelect)
                    edit.CustomDisplayText += new CustomDisplayTextEventHandler(edit_CustomDisplayText);

                if (ab != null)
                {
                    LookUpEdit lue = s.AdditionalBrowserLookupEdit;
                    if (lue == null)
                    {
                        lue = new LookUpEdit();
                        lue.Tag = s;
                        s.AdditionalBrowserLookupEdit = lue;
                        lue.Properties.AutoHeight = false;
                        lue.Height = 0;
                        lue.Dock = DockStyle.Bottom;
                        lue.EditValueChanging += new ChangingEventHandler(additionalBrowser_EditValueChanging);
                        lue.EditValueChanged += new EventHandler(additionalBrowser_EditValueChanged);
                        PrepareLookup(lue.Properties, s, true);
                        BrowserCache.RefreshCacheForBrowser(s.AdditionalBrowserId);
                        DataView dv = new DataView(BrowserCache.GetBrowserData(s.AdditionalBrowserId, true));
                        dv.RowFilter = s.AdditionalBrowserDisplayFilter;
                        lue.Properties.DataSource = dv;
                        lue.Properties.ValueMember = ab.ValueMember;
                        lue.Properties.DisplayMember = ab.DisplayMember;
                        lue.TabStop = false;
                    }
                    edit.FormatEditValue += new ConvertEditValueEventHandler(edit_FormatEditValue);
                    
                    if (buttonEdit != null)
                    {
                        if (button == null)
                        {
                            if (s.UseExistingButton && buttonEdit.Buttons.Count == 1)
                            {
                                button = buttonEdit.Buttons[0];
                                button.Tag = s;
                            }
                            else
                            {
                                buttonEdit.Buttons.Add(new EditorButton(s, s.AdditionalButton));
                            }
                        }
                    }
                }
                else
                {
                    if (buttonEdit != null)
                    {
                        if (button != null)
                        {
                            buttonEdit.Buttons.RemoveAt(buttonEdit.Buttons.IndexOf(button));
                        }
                    }
                    s.AdditionalBrowserLookupEdit = null;
                }
            }
        }

        void additionalBrowser_EditValueChanging(object sender, ChangingEventArgs e)
        {
            LookUpEdit lue = sender as LookUpEdit;
            
            BrowserSettings s = lue.Tag as BrowserSettings;
            if (s != null)
            {
                s.OnAdditionalBrowserValueChanging(lue.Parent, e);
            }
        }

        void edit_FormatEditValue(object sender, ConvertEditValueEventArgs e)
        {
            BaseEdit edit = sender as BaseEdit;
            BrowserSettings s = null;
            if (edit != null)
            {
                if (AllObjects.ContainsKey(sender))
                    s = AllObjects[sender];
                else
                {
                    object o = GetRealKey(edit.Properties);
                    if (o != null && AllObjects.ContainsKey(o))
                        s = AllObjects[o];
                }
            }
            else
            {
                object o = GetRealKey(sender);
                if (o != null && AllObjects.ContainsKey(o))
                    s = AllObjects[o];
            }

            if (s != null && s.AdditionalBrowserId != null)
            {
                object ob = edit != null ? edit.EditValue : e.Value;
                if (ob != null)
                {
                    ob = BrowserCache.GetDisplayForValue(s.AdditionalBrowserId, ob);
                }
                if (ob != null)
                {
                    e.Value = ob.ToString();
                    e.Handled = true;
                }
            }
        }
        
        List<object> lockEventsFor = new List<object>();

        void edit_CustomDisplayText(object sender, CustomDisplayTextEventArgs e)
        {
            if (lockEventsFor.Contains(sender))
                return;
            lockEventsFor.Add(sender);
            try
            {
                BaseEdit edit = sender as BaseEdit;
                BrowserSettings s = null;
                if (edit != null)
                {
                    if (AllObjects.ContainsKey(edit))
                        s = AllObjects[edit];
                    else
                    {
                        object o = GetRealKey(edit.Properties);
                        if (o != null && AllObjects.ContainsKey(o))
                            s = AllObjects[o];
                    }
                }
                else
                {
                    object o = GetRealKey(sender);
                    if (o != null && AllObjects.ContainsKey(o))
                        s = AllObjects[o];
                }
                object ob = edit != null ? edit.EditValue : e.Value;
                if (s != null && s.Browser != null)
                {
                    if (s.MultiSelect)
                    {
                        if (ob != null && ob is object[])
                        {
                            ob = s.Browser.GetDisplayForValues((object[])ob, s.MultiSelectSeparator);
                            e.DisplayText = ob.ToString();
                        }
                    }
                    else
                    {
                        if (s.Browser.IsValid(true, ob))
                            return;
                    }
                }
                if (s != null && s.AdditionalBrowser != null)
                {
                    if (ob != null)
                    {
                        ob = s.AdditionalBrowser.GetDisplayForValue(ob);
                    }
                    if (ob != null)
                    {
                        e.DisplayText = ob.ToString();
                    }
                }
            }
            finally
            {
                lockEventsFor.Remove(sender);
            }
        }

        void additionalBrowser_EditValueChanged(object sender, EventArgs e)
        {
            LookUpEdit lue = sender as LookUpEdit;
            BaseEdit edit = lue.Parent as BaseEdit;
            if (edit != null)
            {
                edit.RunMethod("LockIsDisplayTextValid");
                edit.EditValue = lue.EditValue;
                
                edit.RunMethod("UnlockIsDisplayTextValid");
                if (edit.Properties.Tag != edit.Properties && edit.Properties.Tag!=null)
                {
                    RepositoryItem rep = edit.Properties.Tag as RepositoryItem;
                    if (rep != null)
                    {
                        IDictionary dic = rep.GetPropertyValue("Links") as IDictionary;
                        if (dic != null)
                        {
                            foreach (object o in dic.Keys)
                            {
                                if (o is BaseEdit)
                                {
                                    (o as BaseEdit).EditValue = edit.EditValue;
                                }
                                if (o is BarEditItem)
                                {
                                    (o as BarEditItem).EditValue = edit.EditValue;
                                }
                            }
                        }
                    }
                }
                Form f = edit.FindForm();
                if (f != null)
                {
                    f.SelectNextControl(edit, true, true, false, true);
                }
                edit.Focus();
            }
            BrowserSettings s = lue.Tag as BrowserSettings;
            if (s != null)
            {
                s.OnAdditionalBrowserValueChanged(edit);
            }
        }

        #endregion

        private void PrepareLookup(RepositoryItemMultiSelectGridEdit rep, BrowserSettings s, bool additional)
        {
            if (rep != null)
            {
                if (!this.IsDesignMode())
                {
                    rep.BeginInit();

                    if (rep.Buttons.Count == 0)
                        rep.CreateDefaultButton();

                    rep.QueryPopUp -= new CancelEventHandler(rep_QueryPopUp);
                    rep.Popup -= new EventHandler(rep_Popup);
                    Browser b = additional ? s.AdditionalBrowser : s.Browser;

                    if (s != null && b != null)
                    {
                       if (s.AllowNewRecords)
                            rep.TextEditStyle = TextEditStyles.Standard;

                        rep.QueryPopUp += new CancelEventHandler(rep_QueryPopUp);
                        rep.Popup += new EventHandler(rep_Popup);

                        rep.PopulateColumns(b);
                        BrowserDisplayType type = GetDisplayType(s, additional);

                        if (type == BrowserDisplayType.ComboDropDown)
                        {
                            rep.HideAllColumns();
                            rep.ShowColumn (b.DisplayMember);
                        }
                    }
                    rep.EndInit();
                }
            }
        }
        private void PrepareLookup(RepositoryItemLookUpEdit rep, BrowserSettings s, bool additional)
        {
            if (rep != null)
            {
                if (!this.IsDesignMode())
                {
                    rep.BeginInit();

                    if (rep.Buttons.Count == 0)
                        rep.CreateDefaultButton();

                    rep.QueryPopUp -= new CancelEventHandler(rep_QueryPopUp);
                    rep.Popup -= new EventHandler(rep_Popup);
                    rep.ProcessNewValue -= new ProcessNewValueEventHandler(rep_ProcessNewValue);
                    Browser b = additional ? s.AdditionalBrowser : s.Browser;

                    if (s != null && b != null)
                    {
                        rep.Columns.Clear();

                        if (s.AllowNewRecords)
                            rep.TextEditStyle = TextEditStyles.Standard;

                        rep.QueryPopUp += new CancelEventHandler(rep_QueryPopUp);
                        rep.Popup += new EventHandler(rep_Popup);
                        rep.ProcessNewValue += new ProcessNewValueEventHandler(rep_ProcessNewValue);
                        
                        BrowserDisplayType type = GetDisplayType(s, additional);

                        if (type == BrowserDisplayType.ComboDropDown)
                        {
                            rep.Columns.Add(BrowserTools.CreateColumn(b.Columns[b.DisplayMember]));
                        }
                        else
                        {
                            foreach (BrowserColumn col in b.Columns)
                            {
                                rep.Columns.Add(BrowserTools.CreateColumn(col));
                            }
                        }
                        int w = 0;
                        foreach (LookUpColumnInfo l in rep.Columns)
                        {
                            if (l.Visible)
                                w += l.Width;
                        }
                        if (rep.PopupWidth < w)
                            rep.PopupWidth = w;
                    }
                    rep.EndInit();
                }
            }
        }

        private void PrepareLookup(RepositoryItemGridLookUpEdit rep, BrowserSettings s, bool additional)
        {
            if (rep != null)
            {
                rep.BeginInit();
                if (!this.IsDesignMode())
                {
                    if (rep.Buttons.Count == 0)
                        rep.CreateDefaultButton();
                }
                rep.ProcessNewValue -= new ProcessNewValueEventHandler(rep_ProcessNewValue);
                rep.QueryPopUp -= new CancelEventHandler(rep_QueryPopUp);
                rep.Popup -= new EventHandler(rep_Popup);
               
                Browser b = additional ? s.AdditionalBrowser : s.Browser;

                if (s != null && b != null)
                {
                    rep.View.Columns.Clear();

                    if (s.AllowNewRecords)
                        rep.TextEditStyle = TextEditStyles.Standard;

                    rep.ProcessNewValue += new ProcessNewValueEventHandler(rep_ProcessNewValue);
                    rep.QueryPopUp += new CancelEventHandler(rep_QueryPopUp);
                    rep.Popup += new EventHandler(rep_Popup);
                    rep.View.Name = rep.Name + "View";
                    BrowserDisplayType type = GetDisplayType(s, additional);

                    if (type == BrowserDisplayType.ComboDropDown)
                    {
                        rep.View.Columns.Add(BrowserTools.CreateColumn(b.Columns[b.DisplayMember], rep.View, this));
                    }
                    else
                    {
                        foreach (BrowserColumn col in b.Columns)
                        {
                            rep.View.Columns.Add(BrowserTools.CreateColumn(col, rep.View, this));
                        }
                    }
                }
                rep.EndInit();
            }
        }

        private BrowserDisplayType GetDisplayType(BrowserSettings s, bool additional)
        {
            BrowserDisplayType type = BrowserDisplayType.DropDown;
            BrowserSettingsDisplayType t = additional ? s.AdditionalBrowserDisplayType : s.DisplayType;
            switch (t)
            {
                case BrowserSettingsDisplayType.ComboDropDown:
                    type = BrowserDisplayType.ComboDropDown;
                    break;
                case BrowserSettingsDisplayType.DialogWindow:
                    type = BrowserDisplayType.DialogWindow;
                    break;
                case BrowserSettingsDisplayType.DropDown:
                    type = BrowserDisplayType.DropDown;
                    break;
                case BrowserSettingsDisplayType.Default:
                    type = additional ? s.AdditionalBrowser.DisplayType : s.Browser.DisplayType;
                    break;
                case BrowserSettingsDisplayType.ConfigSpecified:
                    type = BrowserDisplayType.ConfigSpecified;
                    break;
            }
            if (type == BrowserDisplayType.ConfigSpecified)
            {
                type = BrowserCache.GetBrowserDisplayType(additional ? s.AdditionalBrowser : s.Browser);
            }
            return type;
        }
        
        private void rep_ProcessNewValue(object sender, ProcessNewValueEventArgs e)
        {
            BaseEdit edit = sender as BaseEdit;
            BrowserSettings s = null;
            Browser b = null;
            if (edit != null)
            {

                if (AllObjects.ContainsKey(edit))
                    s = AllObjects[edit];
                else
                {
                    object o = GetRealKey(edit.Properties);
                    if (o != null && AllObjects.ContainsKey(o))
                        s = AllObjects[o];
                }
                if (s != null)
                {
                    if (!s.AllowNewRecords)
                        return;
                    b = s.Browser;

                    if (b != null)
                    {
                        DataRow row = b.GetTable().NewRow();
                        s.OnCreateNewRow(row, e.DisplayValue.AsString());
                        b.GetTable().Rows.Add(row);
                        edit.Properties.UnLockEvents();
                        edit.EditValue = row[b.ValueMember];
                        edit.Properties.LockEvents();

                        e.Handled = true;
                    }
                }
            }
        }
        
        private void rep_Popup(object sender, EventArgs e)
        {
            BaseEdit edit = sender as BaseEdit;
            BrowserSettings s = null;
            Browser b = null;
            if (edit != null)
            {
                if (edit.Tag != null && edit.Tag is BrowserSettings)
                {
                    s = edit.Tag as BrowserSettings;
                    b = s.AdditionalBrowser;
                }
                else
                {
                    if (AllObjects.ContainsKey(edit))
                        s = AllObjects[edit];
                    else
                    {
                        object o = GetRealKey(edit.Properties);
                        if (o != null && AllObjects.ContainsKey(o))
                            s = AllObjects[o];
                    }
                    if (s != null)
                        b = s.Browser;
                }
            }

            if (s != null && edit is LookUpEdit)
            {
                object popupForm = edit.GetFieldValue("_popupForm");
                if (popupForm != null)
                {
                    object painter = popupForm.GetFieldValue("fPainter");
                    LookUpEditCustomPainter fPainter = painter as LookUpEditCustomPainter;
                    if (fPainter == null)
                    {
                        fPainter = new LookUpEditCustomPainter();
                        popupForm.SetFieldValue("fPainter", fPainter);
                        fPainter.Browser = b;
                        (edit as LookUpEdit).ClosePopup();
                        (edit as LookUpEdit).ShowPopup();
                        return;
                    }
                    if (fPainter != null)
                        fPainter.Browser = b;
                }
            }
        }

        void rep_QueryPopUp(object sender, CancelEventArgs e)
        {
            BaseEdit edit = sender as BaseEdit;
            BrowserSettings s = null;
            Browser b = null;
            bool additional = false;
            bool multiSelect = false;

            if (edit != null)
            {
                if (edit.Tag != null && edit.Tag is BrowserSettings)
                {
                    s = edit.Tag as BrowserSettings;
                    b = s.AdditionalBrowser;
                    additional = true;
                }
                else
                {
                    if (AllObjects.ContainsKey(edit))
                        s = AllObjects[edit];
                    else
                    {
                        object o = GetRealKey(edit.Properties);
                        if (o != null && AllObjects.ContainsKey(o))
                            s = AllObjects[o];
                    }
                    if (s != null)
                    {
                        b = s.Browser;
                        multiSelect = s.MultiSelect;
                    }
                }

                if (s != null && b != null)
                {
                    BrowserDisplayType type = GetDisplayType(s, additional);

                    if (type == BrowserDisplayType.DialogWindow)
                    {
                        e.Cancel = true;
                        if (!edit.Properties.ReadOnly)
                        {
                            ObjectDialogResult dlg = b.ShowDialog(edit.EditValue, false, multiSelect);
                            if (dlg.DialogResult == DialogResult.OK)
                            {
                                edit.EditValue = dlg.Value;
                                if (multiSelect && edit.EditValue != dlg.Value )
                                {
                                    if (edit is LookUpEdit)
                                    {
                                        ChangingEventArgs ea = new ChangingEventArgs(edit.EditValue, dlg.Value);
                                        ((LookUpEdit)edit).ForceEditValueChanging(ea);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
       
        private class CustomChangingEventArgs : ChangingEventArgs
        {
            public CustomChangingEventArgs(object oldValue, object newValue)
                : base(oldValue, newValue)
            {

            }
            private bool isFirstCancel = true;
            public new bool Cancel
            {
                get { return base.Cancel; }
                set
                {
                    if (isFirstCancel)
                    {
                        isFirstCancel = false;
                    }
                    else
                    {
                        base.Cancel = value;
                    }
                }
            }
        }
        protected override BrowserSettings CreateSettings(object target)
        {
            BrowserSettings s = new BrowserSettings(target, this);
            return s;
        }

        public override bool CanExtend(object extendee)
        {
            if (extendee is TextEdit ||
                extendee is RepositoryItemTextEdit ||
                extendee is RepositoryItemGridLookUpEdit ||
                extendee is RepositoryItemMultiSelectGridEdit)
                return true;
            return false;
        }

        public Browser GetBrowser(object browserId)
        {
            if (browserId is Enum || browserId is string)
            {
                return BrowserCache.GetBrowser(browserId);
            }
            return GetBrowserForTarget(browserId);
        }
        public Browser GetBrowserForTarget(object target)
        {
            if (ContainsSettingsFor(target))
                return GetSettings(target).Browser;
            return null;
        }
        public Browser GetAdditionalBrowserForTarget(object target)
        {
            if (ContainsSettingsFor(target))
                return GetSettings(target).AdditionalBrowser;
            return null;
        }
        public DataRow GetRowForEditValue(BaseEdit edit)
        {
            DataRow r = null;
            BrowserSettings s = null;
            if (this.ContainsSettingsFor(edit))
                s = this.GetSettings(edit);
            else if (this.ContainsSettingsFor(edit.Properties))
                s = this.GetSettings(edit);
            if (s != null && s.Browser != null)
                r = s.Browser.GetRowForValue(edit.EditValue);   
            return r;
        }
        public object GetDisplayForEditValue(BaseEdit edit)
        {
            BrowserSettings s = null;
            if (this.ContainsSettingsFor(edit))
                s = this.GetSettings(edit);
            else if (this.ContainsSettingsFor(edit.Properties))
                s = this.GetSettings(edit);
            if (s != null && s.Browser != null)
                return s.Browser.GetDisplayForValue(edit.EditValue);
            return string.Empty;
        }
        public object GetColumnValueForEditValue(BaseEdit edit, string column)
        {
            DataRow r = null;
            BrowserSettings s = null;
            if (this.ContainsSettingsFor(edit))
                s = this.GetSettings(edit);
            else if (this.ContainsSettingsFor(edit.Properties))
                s = this.GetSettings(edit);
            if (s != null && s.BrowserId != null)
                r = BrowserCache.GetRowForValue(s.BrowserId, edit.EditValue, s.DisplayFilter);
            if (r != null)
                return r[column];
            return null;
        }
    }
    
    public class PNButtonEditPainter : ButtonEditPainter
    {
        public override void Draw(ControlGraphicsInfoArgs info)
        {
            base.Draw(info);
        }
        
        protected override void DrawText(ControlGraphicsInfoArgs info)
        {
            DevExpress.XtraEditors.ViewInfo.LookUpEditViewInfo vi = info.ViewInfo as  DevExpress.XtraEditors.ViewInfo.LookUpEditViewInfo;
            if (vi != null && vi.OwnerEdit != null)
            {
                if (vi.OwnerEdit.Text.IsNull())
                {
                    CustomDisplayTextEventArgs e = new CustomDisplayTextEventArgs(vi.OwnerEdit.EditValue, "");
                    vi.OwnerEdit.Properties.RunMethod("RaiseCustomDisplayText", e);
                    vi.SetDisplayText(e.DisplayText);
                }
            }
            base.DrawText(info);
        }
        protected override void DrawContent(ControlGraphicsInfoArgs info)
        {
            //DevExpress.XtraEditors.ViewInfo.LookUpEditViewInfo vi = info.ViewInfo as DevExpress.XtraEditors.ViewInfo.LookUpEditViewInfo;
            //if (!vi.AllowDrawContent)
            //{
            //    if (vi.OwnerEdit!=null && vi.OwnerEdit.Text.IsNull())
            //    {
            //        CustomDisplayTextEventArgs e = new CustomDisplayTextEventArgs(vi.OwnerEdit.EditValue, "");
            //        vi.OwnerEdit.Properties.RunMethod("RaiseCustomDisplayText", e);
            //        if (e.DisplayText.IsNotNull())
            //            vi.OwnerEdit.MaskBox.EditText = e.DisplayText;
            //        //vi.SetDisplayText(e.DisplayText);
            //    }
            //}
            base.DrawContent(info);
        }
    }
    /*
    public class PNLookUpEditViewInfo : LookUpEditViewInfo
    {
        public PNLookUpEditViewInfo(RepositoryItem item)
            : base(item)
        {

        }
        protected override void UpdatePainters()
        {
            base.UpdatePainters();
        }
        public override string DisplayText
        {
            get
            {
                return base.DisplayText;
            }
        }
    }*/
}
